package lion.dev.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;

/**
 * @author lion
 * @date 2011-5-26
 */
public class Zip {

	static {
		System.setProperty("sun.zip.encoding", "GBK");
	}

	public static void compress(String dest, String... files) throws IOException {

		File[] filearr = new File[files.length];

		for (int i = 0; i < files.length; i++) {
			filearr[i] = new File(files[i]);
		}
		compress(dest, filearr);
	}

	public static void compress(String dest, File... files) throws IOException {

		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
		for (File f : files) {
			if (f == null || !f.exists()) {
				continue;
			}
			addFile(f.getParentFile(), f, zos);
		}
		zos.flush();
		zos.close();
	}

	@SuppressWarnings("unchecked")
	public static void uncompress(String src, String dests) throws IOException {

		ZipFile zfile = new ZipFile(new File(src), 1, Charset.forName(System.getProperty("sun.jnu.encoding")));
		File destFile = new File(dests);
		Enumeration<ZipEntry> zentries = (Enumeration<ZipEntry>) zfile.entries();
		ZipEntry ze;
		while (zentries.hasMoreElements()) {
			ze = zentries.nextElement();
			if (ze.isDirectory()) {
				File file = new File(destFile.getAbsolutePath() + "/" + ze.getName());
				file.mkdirs();
				continue;
			}

			OutputStream os = new FileOutputStream(getAbsolutFilePath(destFile, ze.getName()));
			InputStream is = zfile.getInputStream(ze);
			IOUtils.copy(is, os);
			is.close();
			os.close();
		}
		zfile.close();
	}

	private static String getRelatedFileName(File root, File subFile) {

		String result = "";
		if (subFile.equals(root)) {
			result = root.getName();
		} else {
			int idx = root.getAbsolutePath().length();
			if (!root.getAbsolutePath().replaceAll("\\\\", "/").endsWith("/")) {
				idx++;
			}
			result = subFile.getAbsolutePath().substring(idx);
		}

		if (subFile.isDirectory()) {
			result += "/";
		}
		return result;
	}

	private static String getAbsolutFilePath(File dest, String name) {

		File file = new File(dest.getAbsolutePath() + "/" + name);

		if (file.getParentFile() != null) {
			file.getParentFile().mkdirs();
		}
		return file.getAbsolutePath();
	}

	private static void addFile(File root, File subFile, ZipOutputStream zos) throws IOException {

		ZipEntry ze = new ZipEntry(getRelatedFileName(root, subFile));
		zos.putNextEntry(ze);
		if (subFile.isFile()) {
			ze.setSize(subFile.length());
			ze.setTime(subFile.lastModified());
			InputStream is = new FileInputStream(subFile);
			IOUtils.copy(is, zos);
			is.close();
		} else {
			for (File s : subFile.listFiles()) {
				addFile(root, s, zos);
			}
		}
	}
}
